package kz.edu.sdu.itech.pcs.common;

import java.util.SortedSet;
import java.util.Vector;

import org.apache.log4j.Logger;

public class Permutations {
   static Logger log = Logger.getLogger(Permutations.class);

   static Long ONE = Long.valueOf(1);
   static Vector<Vector<Long>> pascal = new Vector<Vector<Long>>();
   static Vector<Long> pn = new Vector<Long>();
   static {
      Vector<Long> x = new Vector<Long>();
      x.add(ONE);
      pascal.add(x);
      pn.add(ONE);
   }
   static int cn = 0;

   //===================================
   static SortedSet<Character> set;
   static Character[] alf;
   static int n = 0;

   //==================================

   public static void countTo(int n) {
      for (int i = cn + 1; i <= n; i++) {
         Vector<Long> tmp = new Vector<Long>(i + 1);
         Vector<Long> prev = pascal.get(i - 1);
         tmp.add(0, ONE);
         for (int j = 1; j < i; j++) {
            tmp.add(prev.get(j - 1) + prev.get(j));
         }
         tmp.add(i, ONE);
         pascal.add(tmp);
      }
      cn = n;
   }

   public static long getCnm(int n, int m) {
      if (cn < n) {
         countTo(n);
      }
      return pascal.get(n).get(m);
   }

   public static long getPnm(int m, int n) {
      if (pn.size() - 1 < m) {
         long x = getPnm(m - 1, n);
         pn.add(x * n);
      }
      return pn.get(m);
   }

   public static void setAlphabet(Alphabet a) {
      set = a.getSet();
      alf = a.getArray();
      n = alf.length;
   }

   public static String getByNum(Alphabet a, long x, int m) {
      return getByNum(x, m);
   }

   public static String getByNum(long x, int m) {
      StringBuffer sb = new StringBuffer();
      long p = getPnm(m - 1, n);
      long xx = x;
      int k = 0;
      while (xx - p > 0) {
         k++;
         xx -= p;
      }
      sb.append(alf[k]);
      if (m - 1 > 0)
         sb.append(getByNum(xx, m - 1));
      return sb.toString();
   }

   public static int hash(String str) {
      int result = 0;
      for (int i = 0; i < str.length(); i++) {
         result = (result + str.charAt(i)) % 1000;
      }
      return result;
   }
}
